/*
 * (C) Copyright 2005- ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 *
 * In applying this licence, ECMWF does not waive the privileges and immunities granted to it by
 * virtue of its status as an intergovernmental organisation nor does it submit to any jurisdiction.
 */

/*! \file eccodes.h
  \brief The ecCodes C header file

  This is the only file that must be included to use the ecCodes library
  from C.
*/

#ifndef eccodes_H
#define eccodes_H

#ifdef __cplusplus
extern "C" {
#endif

#define CODES_VERSION ECCODES_VERSION

/* sections */
#define CODES_SECTION_PRODUCT GRIB_SECTION_PRODUCT
#define CODES_SECTION_GRID GRIB_SECTION_GRID
#define CODES_SECTION_LOCAL GRIB_SECTION_LOCAL
#define CODES_SECTION_DATA GRIB_SECTION_DATA
#define CODES_SECTION_BITMAP GRIB_SECTION_BITMAP

/* LOG MODES
Log mode for information for processing information
*/
#define CODES_LOG_INFO GRIB_LOG_INFO
#define CODES_LOG_WARNING GRIB_LOG_WARNING
#define CODES_LOG_ERROR GRIB_LOG_ERROR
#define CODES_LOG_FATAL GRIB_LOG_FATAL
#define CODES_LOG_DEBUG GRIB_LOG_DEBUG

/* Types */
#define CODES_TYPE_UNDEFINED GRIB_TYPE_UNDEFINED
#define CODES_TYPE_LONG GRIB_TYPE_LONG
#define CODES_TYPE_DOUBLE GRIB_TYPE_DOUBLE
#define CODES_TYPE_STRING GRIB_TYPE_STRING
#define CODES_TYPE_BYTES GRIB_TYPE_BYTES
#define CODES_TYPE_SECTION GRIB_TYPE_SECTION
#define CODES_TYPE_LABEL GRIB_TYPE_LABEL
#define CODES_TYPE_MISSING GRIB_TYPE_MISSING

/* Missing values */
#define CODES_MISSING_LONG GRIB_MISSING_LONG
#define CODES_MISSING_DOUBLE GRIB_MISSING_DOUBLE

/*set spec flags*/
#define CODES_UTIL_SET_SPEC_FLAGS_ONLY_PACKING GRIB_UTIL_SET_SPEC_FLAGS_ONLY_PACKING

/* Dump option flags*/
#define CODES_DUMP_FLAG_READ_ONLY GRIB_DUMP_FLAG_READ_ONLY
#define CODES_DUMP_FLAG_DUMP_OK GRIB_DUMP_FLAG_DUMP_OK
#define CODES_DUMP_FLAG_VALUES GRIB_DUMP_FLAG_VALUES
#define CODES_DUMP_FLAG_CODED GRIB_DUMP_FLAG_CODED
#define CODES_DUMP_FLAG_OCTET GRIB_DUMP_FLAG_OCTET
#define CODES_DUMP_FLAG_ALIASES GRIB_DUMP_FLAG_ALIASES
#define CODES_DUMP_FLAG_TYPE GRIB_DUMP_FLAG_TYPE
#define CODES_DUMP_FLAG_HEXADECIMAL GRIB_DUMP_FLAG_HEXADECIMAL
#define CODES_DUMP_FLAG_NO_DATA GRIB_DUMP_FLAG_NO_DATA
#define CODES_DUMP_FLAG_ALL_DATA GRIB_DUMP_FLAG_ALL_DATA
#define CODES_DUMP_FLAG_ALL_ATTRIBUTES GRIB_DUMP_FLAG_ALL_ATTRIBUTES

/* codes_nearest flags */
#define CODES_NEAREST_SAME_GRID GRIB_NEAREST_SAME_GRID
#define CODES_NEAREST_SAME_DATA GRIB_NEAREST_SAME_DATA
#define CODES_NEAREST_SAME_POINT GRIB_NEAREST_SAME_POINT

/*! Iteration is carried out on all the keys available in the message
\ingroup keys_iterator
\see codes_keys_iterator_new
*/
#define CODES_KEYS_ITERATOR_ALL_KEYS GRIB_KEYS_ITERATOR_ALL_KEYS

/*! read only keys are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new
*/
#define CODES_KEYS_ITERATOR_SKIP_READ_ONLY GRIB_KEYS_ITERATOR_SKIP_READ_ONLY

/*! optional keys are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_SKIP_OPTIONAL GRIB_KEYS_ITERATOR_SKIP_OPTIONAL

/*! edition specific keys are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_SKIP_EDITION_SPECIFIC GRIB_KEYS_ITERATOR_SKIP_EDITION_SPECIFIC

/*! coded keys are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_SKIP_CODED GRIB_KEYS_ITERATOR_SKIP_CODED

/*! computed keys are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_SKIP_COMPUTED GRIB_KEYS_ITERATOR_SKIP_COMPUTED

/*! duplicates of a key are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_SKIP_DUPLICATES GRIB_KEYS_ITERATOR_SKIP_DUPLICATES

/*! function keys are skipped by keys iterator.
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_SKIP_FUNCTION GRIB_KEYS_ITERATOR_SKIP_FUNCTION

/*!  only keys present in the dump
\ingroup keys_iterator
\see codes_keys_iterator_new */
#define CODES_KEYS_ITERATOR_DUMP_ONLY GRIB_KEYS_ITERATOR_DUMP_ONLY

typedef struct grib_values codes_values;
typedef struct grib_key_value_list codes_key_value_list;

/*! Codes handle,   structure giving access to parsed values by keys
    \ingroup codes_handle
    \struct codes_handle
*/
typedef struct grib_handle codes_handle;

/*! GRIB multi-field handle, structure used to build multi-field messages.
    \ingroup codes_handle
    \struct codes_multi_handle
 */
typedef struct grib_multi_handle codes_multi_handle;

/*! Codes context,  structure containing the memory methods, the parsers and the formats.
    \ingroup codes_context
    \struct codes_context
*/
typedef struct grib_context codes_context;

/*! GRIB geoiterator, structure supporting a geographic iteration of values in a GRIB message.
    \ingroup iterators
    \struct codes_iterator
*/
typedef struct grib_iterator codes_iterator;

/*! Codes nearest, structure used to find the nearest points of a latitude longitude point in a GRIB message.
    \ingroup iterators
    \struct codes_nearest
*/
typedef struct grib_nearest codes_nearest;
typedef struct grib_box codes_box;
typedef struct grib_points codes_points;

/*! Codes keys iterator. Iterator over keys.
    \ingroup keys_iterator
    \struct codes_keys_iterator
*/
typedef struct grib_keys_iterator codes_keys_iterator;
typedef struct bufr_keys_iterator codes_bufr_keys_iterator;

typedef struct grib_fieldset codes_fieldset;
typedef struct grib_order_by codes_order_by;
typedef struct grib_where codes_where;
typedef struct grib_sarray codes_sarray;
typedef struct grib_oarray codes_oarray;
typedef struct grib_darray codes_darray;
typedef struct grib_iarray codes_iarray;
typedef struct grib_vdarray codes_vdarray;
typedef struct grib_vsarray codes_vsarray;
typedef struct grib_viarray codes_viarray;
typedef struct grib_string_list codes_string_list;
typedef struct grib_util_packing_spec codes_util_packing_spec;
typedef struct grib_util_grid_spec codes_util_grid_spec;





/*! \defgroup context The context object
 The context is a long life configuration object of eccodes.
 It is used to define special allocation and free routines or
 to set special eccodes behaviours and variables.
 */
/*! @{ */



/*! @} */








void codes_check(const char* call, const char* file, int line, int e, const char* msg);
#define CODES_CHECK(a, msg) GRIB_CHECK(a, msg)
#define CODES_CHECK_NOLINE(a, msg) GRIB_CHECK_NOLINE(a, msg)


int codes_set_values(codes_handle* h, codes_values* codes_values, size_t arg_count);
codes_handle* codes_handle_new_from_partial_message_copy(codes_context* c, const void* data, size_t size);
codes_handle* codes_handle_new_from_partial_message(codes_context* c, const void* data, size_t buflen);


/* The truncation is the Gaussian number (or order) */
int codes_get_gaussian_latitudes(long truncation, double* latitudes);

int codes_julian_to_datetime(double jd, long* year, long* month, long* day, long* hour, long* minute, long* second);
int codes_datetime_to_julian(long year, long month, long day, long hour, long minute, long second, double* jd);
long codes_julian_to_date(long jdate);
long codes_date_to_julian(long ddate);

void codes_get_reduced_row(long pl, double lon_first, double lon_last, long* npoints, long* ilon_first, long* ilon_last);
void codes_get_reduced_row_p(long pl, double lon_first, double lon_last, long* npoints, double* olon_first, double* olon_last);


/* read products */
int codes_get_message_offset(const codes_handle* h, off_t* offset);
int codes_get_message_size(const codes_handle* h, size_t* size);
int codes_get_product_kind(const codes_handle* h, ProductKind* product_kind);
int codes_check_message_header(const void* bytes, size_t length, ProductKind product);
int codes_check_message_footer(const void* bytes, size_t length, ProductKind product);

codes_box* codes_box_new(codes_handle* h, int* error);
codes_points* codes_box_get_points(codes_box* box, double north, double west, double south, double east, int* err);
int codes_points_get_values(codes_handle* h, codes_points* points, double* val);

/* --------------------------------------- */

#define CODES_UTIL_GRID_SPEC_REGULAR_LL GRIB_UTIL_GRID_SPEC_REGULAR_LL
#define CODES_UTIL_GRID_SPEC_ROTATED_LL GRIB_UTIL_GRID_SPEC_ROTATED_LL
#define CODES_UTIL_GRID_SPEC_REGULAR_GG GRIB_UTIL_GRID_SPEC_REGULAR_GG
#define CODES_UTIL_GRID_SPEC_ROTATED_GG GRIB_UTIL_GRID_SPEC_ROTATED_GG
#define CODES_UTIL_GRID_SPEC_REDUCED_GG GRIB_UTIL_GRID_SPEC_REDUCED_GG
#define CODES_UTIL_GRID_SPEC_SH GRIB_UTIL_GRID_SPEC_SH
#define CODES_UTIL_GRID_SPEC_REDUCED_LL GRIB_UTIL_GRID_SPEC_REDUCED_LL
#define CODES_UTIL_GRID_SPEC_POLAR_STEREOGRAPHIC GRIB_UTIL_GRID_SPEC_POLAR_STEREOGRAPHIC
#define CODES_UTIL_GRID_SPEC_REDUCED_ROTATED_GG GRIB_UTIL_GRID_SPEC_REDUCED_ROTATED_GG
#define CODES_UTIL_GRID_SPEC_LAMBERT_AZIMUTHAL_EQUAL_AREA GRIB_UTIL_GRID_SPEC_LAMBERT_AZIMUTHAL_EQUAL_AREA
#define CODES_UTIL_GRID_SPEC_LAMBERT_CONFORMAL GRIB_UTIL_GRID_SPEC_LAMBERT_CONFORMAL
#define CODES_UTIL_GRID_SPEC_UNSTRUCTURED GRIB_UTIL_GRID_SPEC_UNSTRUCTURED

#define CODES_UTIL_PACKING_TYPE_SAME_AS_INPUT GRIB_UTIL_PACKING_TYPE_SAME_AS_INPUT
#define CODES_UTIL_PACKING_TYPE_SPECTRAL_COMPLEX GRIB_UTIL_PACKING_TYPE_SPECTRAL_COMPLEX
#define CODES_UTIL_PACKING_TYPE_SPECTRAL_SIMPLE GRIB_UTIL_PACKING_TYPE_SPECTRAL_SIMPLE
#define CODES_UTIL_PACKING_TYPE_JPEG GRIB_UTIL_PACKING_TYPE_JPEG
#define CODES_UTIL_PACKING_TYPE_GRID_COMPLEX GRIB_UTIL_PACKING_TYPE_GRID_COMPLEX
#define CODES_UTIL_PACKING_TYPE_GRID_SIMPLE GRIB_UTIL_PACKING_TYPE_GRID_SIMPLE
#define CODES_UTIL_PACKING_TYPE_GRID_SIMPLE_MATRIX GRIB_UTIL_PACKING_TYPE_GRID_SIMPLE_MATRIX
#define CODES_UTIL_PACKING_TYPE_GRID_SECOND_ORDER GRIB_UTIL_PACKING_TYPE_GRID_SECOND_ORDER
#define CODES_UTIL_PACKING_TYPE_CCSDS GRIB_UTIL_PACKING_TYPE_CCSDS
#define CODES_UTIL_PACKING_TYPE_IEEE GRIB_UTIL_PACKING_TYPE_IEEE
#define CODES_UTIL_PACKING_SAME_AS_INPUT GRIB_UTIL_PACKING_SAME_AS_INPUT
#define CODES_UTIL_PACKING_USE_PROVIDED GRIB_UTIL_PACKING_USE_PROVIDED

#define CODES_UTIL_ACCURACY_SAME_BITS_PER_VALUES_AS_INPUT GRIB_UTIL_ACCURACY_SAME_BITS_PER_VALUES_AS_INPUT
#define CODES_UTIL_ACCURACY_USE_PROVIDED_BITS_PER_VALUES GRIB_UTIL_ACCURACY_USE_PROVIDED_BITS_PER_VALUES
#define CODES_UTIL_ACCURACY_SAME_DECIMAL_SCALE_FACTOR_AS_INPUT GRIB_UTIL_ACCURACY_SAME_DECIMAL_SCALE_FACTOR_AS_INPUT
#define CODES_UTIL_ACCURACY_USE_PROVIDED_DECIMAL_SCALE_FACTOR GRIB_UTIL_ACCURACY_USE_PROVIDED_DECIMAL_SCALE_FACTOR


codes_handle* codes_grib_util_set_spec(codes_handle* h,
                                       const codes_util_grid_spec* grid_spec,
                                       const codes_util_packing_spec* packing_spec, /* NULL for defaults (same as input) */
                                       int flags,
                                       const double* data_values,
                                       size_t data_values_count,
                                       int* err);

/* EXPERIMENTAL FEATURE
 * Build an array of message headers from input BUFR file.
 * result = array of 'codes_bufr_header' structs with 'num_messages' elements.
 *          This array should be freed by the caller.
 * num_messages = number of messages found in the input file.
 * strict = If 1 means fail if any message is invalid.
 * returns 0 if OK, integer value on error.
 */
int codes_bufr_extract_headers_malloc(codes_context* c, const char* filename, codes_bufr_header** result, int* num_messages, int strict_mode);
int codes_bufr_header_get_string(codes_bufr_header* bh, const char* key, char* val, size_t* len);

/* EXPERIMENTAL FEATURE
 * Build an array of message offsets from input file. The client has to supply the ProductKind (GRIB, BUFR etc)
 * result = array of offsets with 'num_messages' elements.
 *          This array should be freed by the caller.
 * num_messages = number of messages found in the input file.
 * strict_mode  = If 1 means fail if any message is invalid.
 * returns 0 if OK, integer value on error.
 */
int codes_extract_offsets_malloc(grib_context* c, const char* filename, ProductKind product, off_t** offsets, int* num_messages, int strict_mode);

/* --------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif
/* This part is automatically generated by ./errors.pl, do not edit */
#ifndef eccodes_errors_H
#define eccodes_errors_H
/*! \defgroup errors Error codes
Error codes returned by the eccodes functions.
*/
/*! @{*/
/** No error */
#define CODES_SUCCESS GRIB_SUCCESS
/** End of resource reached */
#define CODES_END_OF_FILE GRIB_END_OF_FILE
/** Internal error */
#define CODES_INTERNAL_ERROR GRIB_INTERNAL_ERROR
/** Passed buffer is too small */
#define CODES_BUFFER_TOO_SMALL GRIB_BUFFER_TOO_SMALL
/** Function not yet implemented */
#define CODES_NOT_IMPLEMENTED GRIB_NOT_IMPLEMENTED
/** Missing 7777 at end of message */
#define CODES_7777_NOT_FOUND GRIB_7777_NOT_FOUND
/** Passed array is too small */
#define CODES_ARRAY_TOO_SMALL GRIB_ARRAY_TOO_SMALL
/** File not found */
#define CODES_FILE_NOT_FOUND GRIB_FILE_NOT_FOUND
/** Code not found in code table */
#define CODES_CODE_NOT_FOUND_IN_TABLE GRIB_CODE_NOT_FOUND_IN_TABLE
/** Array size mismatch */
#define CODES_WRONG_ARRAY_SIZE GRIB_WRONG_ARRAY_SIZE
/** Key/value not found */
#define CODES_NOT_FOUND GRIB_NOT_FOUND
/** Input output problem */
#define CODES_IO_PROBLEM GRIB_IO_PROBLEM
/** Message invalid */
#define CODES_INVALID_MESSAGE GRIB_INVALID_MESSAGE
/** Decoding invalid */
#define CODES_DECODING_ERROR GRIB_DECODING_ERROR
/** Encoding invalid */
#define CODES_ENCODING_ERROR GRIB_ENCODING_ERROR
/** Code cannot unpack because of string too small */
#define CODES_NO_MORE_IN_SET GRIB_NO_MORE_IN_SET
/** Problem with calculation of geographic attributes */
#define CODES_GEOCALCULUS_PROBLEM GRIB_GEOCALCULUS_PROBLEM
/** Memory allocation error */
#define CODES_OUT_OF_MEMORY GRIB_OUT_OF_MEMORY
/** Value is read only */
#define CODES_READ_ONLY GRIB_READ_ONLY
/** Invalid argument */
#define CODES_INVALID_ARGUMENT GRIB_INVALID_ARGUMENT
/** Null handle */
#define CODES_NULL_HANDLE GRIB_NULL_HANDLE
/** Invalid section number */
#define CODES_INVALID_SECTION_NUMBER GRIB_INVALID_SECTION_NUMBER
/** Value cannot be missing */
#define CODES_VALUE_CANNOT_BE_MISSING GRIB_VALUE_CANNOT_BE_MISSING
/** Wrong message length */
#define CODES_WRONG_LENGTH GRIB_WRONG_LENGTH
/** Invalid key type */
#define CODES_INVALID_TYPE GRIB_INVALID_TYPE
/** Unable to set step */
#define CODES_WRONG_STEP GRIB_WRONG_STEP
/** Wrong units for step (step must be integer) */
#define CODES_WRONG_STEP_UNIT GRIB_WRONG_STEP_UNIT
/** Invalid file id */
#define CODES_INVALID_FILE GRIB_INVALID_FILE
/** Invalid grib id */
#define CODES_INVALID_GRIB GRIB_INVALID_GRIB
/** Invalid index id */
#define CODES_INVALID_INDEX GRIB_INVALID_INDEX
/** Invalid iterator id */
#define CODES_INVALID_ITERATOR GRIB_INVALID_ITERATOR
/** Invalid keys iterator id */
#define CODES_INVALID_KEYS_ITERATOR GRIB_INVALID_KEYS_ITERATOR
/** Invalid nearest id */
#define CODES_INVALID_NEAREST GRIB_INVALID_NEAREST
/** Invalid order by */
#define CODES_INVALID_ORDERBY GRIB_INVALID_ORDERBY
/** Missing a key from the fieldset */
#define CODES_MISSING_KEY GRIB_MISSING_KEY
/** The point is out of the grid area */
#define CODES_OUT_OF_AREA GRIB_OUT_OF_AREA
/** Concept no match */
#define CODES_CONCEPT_NO_MATCH GRIB_CONCEPT_NO_MATCH
/** Hash array no match */
#define CODES_HASH_ARRAY_NO_MATCH GRIB_HASH_ARRAY_NO_MATCH
/** Definitions files not found */
#define CODES_NO_DEFINITIONS GRIB_NO_DEFINITIONS
/** Wrong type while packing */
#define CODES_WRONG_TYPE GRIB_WRONG_TYPE
/** End of resource */
#define CODES_END GRIB_END
/** Unable to code a field without values */
#define CODES_NO_VALUES GRIB_NO_VALUES
/** Grid description is wrong or inconsistent */
#define CODES_WRONG_GRID GRIB_WRONG_GRID
/** End of index reached */
#define CODES_END_OF_INDEX GRIB_END_OF_INDEX
/** Null index */
#define CODES_NULL_INDEX GRIB_NULL_INDEX
/** End of resource reached when reading message */
#define CODES_PREMATURE_END_OF_FILE GRIB_PREMATURE_END_OF_FILE
/** An internal array is too small */
#define CODES_INTERNAL_ARRAY_TOO_SMALL GRIB_INTERNAL_ARRAY_TOO_SMALL
/** Message is too large for the current architecture */
#define CODES_MESSAGE_TOO_LARGE GRIB_MESSAGE_TOO_LARGE
/** Constant field */
#define CODES_CONSTANT_FIELD GRIB_CONSTANT_FIELD
/** Switch unable to find a matching case */
#define CODES_SWITCH_NO_MATCH GRIB_SWITCH_NO_MATCH
/** Underflow */
#define CODES_UNDERFLOW GRIB_UNDERFLOW
/** Message malformed */
#define CODES_MESSAGE_MALFORMED GRIB_MESSAGE_MALFORMED
/** Index is corrupted */
#define CODES_CORRUPTED_INDEX GRIB_CORRUPTED_INDEX
/** Invalid number of bits per value */
#define CODES_INVALID_BPV GRIB_INVALID_BPV
/** Edition of two messages is different */
#define CODES_DIFFERENT_EDITION GRIB_DIFFERENT_EDITION
/** Value is different */
#define CODES_VALUE_DIFFERENT GRIB_VALUE_DIFFERENT
/** Invalid key value */
#define CODES_INVALID_KEY_VALUE GRIB_INVALID_KEY_VALUE
/** String is smaller than requested */
#define CODES_STRING_TOO_SMALL GRIB_STRING_TOO_SMALL
/** Wrong type conversion */
#define CODES_WRONG_CONVERSION GRIB_WRONG_CONVERSION
/** Missing BUFR table entry for descriptor */
#define CODES_MISSING_BUFR_ENTRY GRIB_MISSING_BUFR_ENTRY
/** Null pointer */
#define CODES_NULL_POINTER GRIB_NULL_POINTER
/** Attribute is already present, cannot add */
#define CODES_ATTRIBUTE_CLASH GRIB_ATTRIBUTE_CLASH
/** Too many attributes. Increase MAX_ACCESSOR_ATTRIBUTES */
#define CODES_TOO_MANY_ATTRIBUTES GRIB_TOO_MANY_ATTRIBUTES
/** Attribute not found. */
#define CODES_ATTRIBUTE_NOT_FOUND GRIB_ATTRIBUTE_NOT_FOUND
/** Edition not supported. */
#define CODES_UNSUPPORTED_EDITION GRIB_UNSUPPORTED_EDITION
/** Value out of coding range */
#define CODES_OUT_OF_RANGE GRIB_OUT_OF_RANGE
/** Size of bitmap is incorrect */
#define CODES_WRONG_BITMAP_SIZE GRIB_WRONG_BITMAP_SIZE
/** Functionality not enabled */
#define CODES_FUNCTIONALITY_NOT_ENABLED GRIB_FUNCTIONALITY_NOT_ENABLED
/*! @}*/
#endif
